package org.truenewx.tnxjeex.discovery.config;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.loadbalancer.LoadBalancerAlgorithm;
import com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancer;
import com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancerClientConfiguration;
import com.alibaba.cloud.nacos.loadbalancer.ServiceInstanceFilter;
import com.alibaba.cloud.nacos.util.InetIPv6Utils;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.truenewx.tnxjee.core.beans.factory.WrappedObjectProvider;
import org.truenewx.tnxjeex.discovery.loadbalancer.DefaultServiceInstanceListFilter;
import org.truenewx.tnxjeex.discovery.loadbalancer.FilterableServiceInstanceListSupplier;
import org.truenewx.tnxjeex.discovery.loadbalancer.ServiceInstanceListFilter;

@Import(NacosLoadBalancerClientConfiguration.BlockingSupportConfiguration.class)
public class LoadBalancerConfiguration extends NacosLoadBalancerClientConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public ServiceInstanceListFilter serviceInstanceListFilter() {
        return new DefaultServiceInstanceListFilter();
    }

    @Override
    public ReactorLoadBalancer<ServiceInstance> nacosLoadBalancer(Environment environment,
            LoadBalancerClientFactory loadBalancerClientFactory, NacosDiscoveryProperties nacosDiscoveryProperties,
            InetIPv6Utils inetIPv6Utils, List<ServiceInstanceFilter> serviceInstanceFilters,
            List<LoadBalancerAlgorithm> loadBalancerAlgorithms) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        ObjectProvider<ServiceInstanceListSupplier> supplierProvider = loadBalancerClientFactory.getLazyProvider(name,
                ServiceInstanceListSupplier.class);
        ServiceInstanceListFilter filter = serviceInstanceListFilter();
        supplierProvider = new WrappedObjectProvider<>(supplierProvider,
                supplier -> new FilterableServiceInstanceListSupplier(supplier, filter));
        Map<String, LoadBalancerAlgorithm> loadBalancerAlgorithmMap = new HashMap<>();
        for (LoadBalancerAlgorithm algorithm : loadBalancerAlgorithms) {
            loadBalancerAlgorithmMap.put(algorithm.getServiceId(), algorithm);
        }
        return new NacosLoadBalancer(supplierProvider, name, nacosDiscoveryProperties, inetIPv6Utils,
                serviceInstanceFilters, loadBalancerAlgorithmMap);
    }

}
